package com.waps;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.Locale;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import android.content.res.Configuration;
import android.util.DisplayMetrics;
import android.view.WindowManager;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.AsyncTask;
import android.telephony.TelephonyManager;

public final class AppConnect
{
    private ConnectTask connectTask = null;
    private Context context = null;

    private static AppConnect appConnectInstance = null;
    private static AppURLConnection appURLConnection = null;
    private static DisplayAd displayAd = null;

    private String deviceID = "";
    private String deviceName = "";
    private String deviceType = "";
    private String deviceOSVersion = "";
    private String deviceCountryCode = "";
    private String deviceLanguage = "";
    private String appID = "";
    private String appVersion = "";
    private String libraryVersion = "";
    private String deviceUserID = "";

    private String spendPoints = "";

    private String clientPackage = "";
    private String urlParams = "";
    private String referralURL = "";
    private String deviceScreenDensity = "";
    private String deviceScreenLayoutSize = "";

    // URL 参数名.
    final String DEVICE_ID_NAME							= "udid";				// 该设备的唯一ID (IMEI or MEID).
    final String DEVICE_NAME							= "device_name";		// 具体的设备名(iPod touch 2G, iPhone 3GS, ...)
    final String DEVICE_TYPE_NAME						= "device_type";		// 平台类型 (Android, iPhone, iPad).
    final String DEVICE_OS_VERSION_NAME					= "os_version";			// 操作系统版本.
    final String DEVICE_COUNTRY_CODE					= "country_code";		// 国家代码.
    final String DEVICE_LANGUAGE						= "language";			// 语言代码.
    final String APP_ID_NAME							= "app_id";				// 应用程序ID.
    final String APP_VERSION_NAME						= "app_version";		// 应用程序版本.
    final String CONNECT_LIBRARY_VERSION_NAME			= "sdk_version";	    //  SDK版本.
    final String USER_ID								= "publisher_user_id";	// 此设备的用户ID.
    final String APP_ACT								= "act";	            //
    final String USER_STR								= "userid";	            // 应用自定义的用户ID.

    final String SPEND_POINTS                           = "points";			// 消费点数／金额.

    static final String SERVICE_URL 					= "http://app.dwap.com:8000/action/";
    static final String BASE_REDIRECT_DOMAIN 			= "app.dwap.com";
    static final String CONNECT_URL_PATH				= "connect/active?";
    static final String USERDATA_URL_PATH				= "account/getinfo?";
    static final String SPEND_POINTS_URL_PATH			= "account/spend?";
    public static final String LIBRARY_VERSION_NUMBER	= "1.1.b";
    static final String DEVICE_PLATFORM_TYPE			= "android";

    static final String CONNECT 						= "AppConnect";
    static final String EMULATOR_DEVICE_ID 			    = "emulatorDeviceId";
    static final String PRIMARY_COLOR				    = "PrimaryColor";
    static final String PREFERENCE 						= "appPrefrences";
    static final String REFERRAL_URL 					= "InstallReferral";
    static final String CONTAINS_EXTERNAL_DATA			= "containsExternalData";

    static final String EXTRA_URL_PARAMS				= "URL_PARAMS";
    static final String EXTRA_CLIENT_PACKAGE			= "CLIENT_PACKAGE";
    static final String EXTRA_USER_ID					= "USER_ID";

    final String DEVICE_SCREEN_DENSITY					= "density";		// 屏幕密度.
    final String DEVICE_SCREEN_LAYOUT_SIZE				= "layout_size";	// 布局大小.

    // Offers相关
    private static UpdatePointsNotifier updatePointsNotifier;
    private ConnectGetPointsTask connectGetPointsTask = null;

    //    private static SpendPointsNotifier spendPointsNotifier;
    private ConnectSpendPointsTask connectSpendPointsTask = null;

    //虚拟道具 相关.
    private int primaryColor;

    /**
     * 连接并通知服务器，此设备已运行当前程序。
     * @param context 上下文
     * @return AppConnect实例
     */
    public static AppConnect getInstance(Context context)
    {
        if (appURLConnection == null)
            appURLConnection = new AppURLConnection();

        if (appConnectInstance == null)
            appConnectInstance = new AppConnect(context);

        if (displayAd == null)
            displayAd = new DisplayAd(context);

        return appConnectInstance;
    }

    public static AppConnect getInstance(Context context,String user_str)
    {
        if (appURLConnection == null)
            appURLConnection = new AppURLConnection();

        if (appConnectInstance == null)
            appConnectInstance = new AppConnect(context,user_str);

        if (displayAd == null)
            displayAd = new DisplayAd(context);

        return appConnectInstance;
    }


    /**
     * 获取到设备和元数据信息并格式化为URL参数格式
     * @param //context the Activity Context
     */
    private AppConnect(Context ctx)
    {
        context = ctx;

        // 填充URL参数中的数据.
        initMetaData();

        // 构建url参数.
        urlParams += DEVICE_ID_NAME + "=" + deviceID + "&";
        urlParams += DEVICE_NAME + "=" + deviceName + "&";
        urlParams += DEVICE_TYPE_NAME + "=" + deviceType + "&";
        urlParams += DEVICE_OS_VERSION_NAME + "=" + deviceOSVersion + "&";
        urlParams += DEVICE_COUNTRY_CODE + "=" + deviceCountryCode + "&";
        urlParams += DEVICE_LANGUAGE + "=" + deviceLanguage + "&";
        urlParams += APP_ID_NAME + "=" + appID + "&";
        urlParams += APP_VERSION_NAME + "=" + appVersion + "&";
        urlParams += CONNECT_LIBRARY_VERSION_NAME + "=" + libraryVersion+"&";
        urlParams += APP_ACT + "=" + ctx.getPackageName()+"."+ctx.getClass().getSimpleName();

        if (deviceScreenDensity.length() > 0 && deviceScreenLayoutSize.length() > 0)
        {
            urlParams += "&";
            urlParams += DEVICE_SCREEN_DENSITY + "=" + deviceScreenDensity + "&";
            urlParams += DEVICE_SCREEN_LAYOUT_SIZE + "=" + deviceScreenLayoutSize;
        }

        AppLog.i(CONNECT, "URL parameters: " + urlParams);

        connectTask = new ConnectTask();
        connectTask.execute();
    }


    /**
     * 获取到设备和元数据信息并格式化为URL参数格式
     * @param //context the Activity Context
     */
    private AppConnect(Context ctx,String user_str)
    {
        context = ctx;

        // 填充URL参数中的数据.
        initMetaData();

        // 构建url参数.
        urlParams += DEVICE_ID_NAME + "=" + deviceID + "&";
        urlParams += DEVICE_NAME + "=" + deviceName + "&";
        urlParams += DEVICE_TYPE_NAME + "=" + deviceType + "&";
        urlParams += DEVICE_OS_VERSION_NAME + "=" + deviceOSVersion + "&";
        urlParams += DEVICE_COUNTRY_CODE + "=" + deviceCountryCode + "&";
        urlParams += DEVICE_LANGUAGE + "=" + deviceLanguage + "&";
        urlParams += APP_ID_NAME + "=" + appID + "&";
        urlParams += APP_VERSION_NAME + "=" + appVersion + "&";
        urlParams += CONNECT_LIBRARY_VERSION_NAME + "=" + libraryVersion+"&";
        urlParams += USER_STR + "=" + user_str+"&";
        urlParams += APP_ACT + "=" + ctx.getPackageName()+"."+ctx.getClass().getSimpleName();

        if (deviceScreenDensity.length() > 0 && deviceScreenLayoutSize.length() > 0)
        {
            urlParams += "&";
            urlParams += DEVICE_SCREEN_DENSITY + "=" + deviceScreenDensity + "&";
            urlParams += DEVICE_SCREEN_LAYOUT_SIZE + "=" + deviceScreenLayoutSize;
        }

        AppLog.i(CONNECT, "URL parameters: " + urlParams);

        connectTask = new ConnectTask();
        connectTask.execute();
    }

    /**
     * 从manifest文件初始化设备信息，这些数据用在每次的连接服务器中
     */
    private void initMetaData()
    {
        PackageManager manager = context.getPackageManager();
        ApplicationInfo info;

        try
        {
            info = manager.getApplicationInfo(context.getPackageName(), PackageManager.GET_META_DATA);

            if (info != null && info.metaData != null)
            {
                // 获取到APP_ID.
                String metaDataValue = info.metaData.getString("WAPS_ID");
                if(metaDataValue==null||"".equals(metaDataValue)){
                    metaDataValue = info.metaData.getString("APP_ID");
                }

                if (metaDataValue != null && !metaDataValue.equals(""))
                {
                    appID = metaDataValue.trim();
                }
                else
                {
                    AppLog.e(CONNECT, "APP_ID can't be empty.");
                    return;
                }

                // 获取到包路径.
                metaDataValue = info.metaData.getString("CLIENT_PACKAGE");
                if (metaDataValue != null && !metaDataValue.equals(""))
                {
                    clientPackage = metaDataValue;
                }
                else
                {
                    AppLog.e(CONNECT, "CLIENT_PACKAGE is missing.");
                    return;
                }

                // 获取应用程序版本.
                PackageInfo packageInfo = manager.getPackageInfo(context.getPackageName(), 0);
                appVersion = packageInfo.versionName;

                // 设备类型.
                deviceType = DEVICE_PLATFORM_TYPE;

                // 设备名.
                deviceName = android.os.Build.MODEL;

                // 操作系统版本.
                deviceOSVersion = android.os.Build.VERSION.RELEASE;

                // 国家和语言代码.
                deviceCountryCode = Locale.getDefault().getCountry();
                deviceLanguage = Locale.getDefault().getLanguage();

                // SDK版本.
                libraryVersion = LIBRARY_VERSION_NUMBER;

                SharedPreferences settings = context.getSharedPreferences(PREFERENCE, 0);

                // 设备ID.
                metaDataValue = info.metaData.getString("DEVICE_ID");

                // 设备ID是否已经存在于 manifest中?
                if (metaDataValue != null && !metaDataValue.equals(""))
                {
                    deviceID = metaDataValue;
                    AppLog.i(CONNECT, "Using manifest device id = " + deviceID);
                }
                else
                {
                    TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);

                    if (telephonyManager != null)
                    {
                        deviceID = telephonyManager.getDeviceId();

                        // 设备ID是否为空?
                        if (deviceID == null || deviceID.length() == 0)
                        {
                            AppLog.e(CONNECT, "Device id is null or empty.");

                            // 设置设备ID为0 如果是空，生成一个模拟的设备ID.
                            deviceID = "0";
                        }

                        //else
                        {
                            try
                            {
                                // 设备ID转为小写.
                                deviceID = deviceID.toLowerCase();

                                Integer devTag = Integer.parseInt(deviceID);

                                // 设备ID是否0.
                                if (devTag.intValue() == 0)
                                {
                                    StringBuffer buff = new StringBuffer();
                                    buff.append("EMULATOR");
                                    String deviceId = settings.getString(EMULATOR_DEVICE_ID, null);

                                    if( deviceId != null && !deviceId.equals(""))
                                    {
                                        deviceID = deviceId;
                                    }
                                    else
                                    {
                                        String constantChars = "1234567890abcdefghijklmnopqrstuvw";
                                        for (int i=0 ; i < 32; i++)
                                        {
                                            int randomChar = (int) ( Math.random()* 100) ;
                                            int ch = randomChar % 30;
                                            buff.append(constantChars.charAt(ch));
                                        }

                                        deviceID = buff.toString().toLowerCase();

                                        SharedPreferences.Editor editor = settings.edit();
                                        editor.putString(EMULATOR_DEVICE_ID, deviceID);
                                        editor.commit();
                                    }
                                }
                            }
                            catch(NumberFormatException ex)
                            {

                            }
                        }
                    }
                    else
                    {
                        deviceID = null;
                    }
                }
                AppLog.w("===============","");
                try
                {
                    DisplayMetrics metrics = new DisplayMetrics();
                    WindowManager windowManager = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
                    windowManager.getDefaultDisplay().getMetrics(metrics);
                    Configuration configuration = context.getResources().getConfiguration();

                    deviceScreenDensity = "" + metrics.densityDpi;
                    deviceScreenLayoutSize = "" + (configuration.screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK);
                    AppLog.w("===============",deviceScreenDensity+"  "+deviceScreenLayoutSize);
                }
                catch (Exception e)
                {

                }

                AppLog.i(CONNECT, "primaryColor: [" + primaryColor + "]");
                AppLog.i(CONNECT, "PRIMARY_COLOR: [" + PRIMARY_COLOR + "]");
                primaryColor = settings.getInt(PRIMARY_COLOR, 0);

                // Get the referral URL
                String tempReferralURL = settings.getString(REFERRAL_URL, null);
                if (tempReferralURL != null && !tempReferralURL.equals(""))
                    referralURL = tempReferralURL;

                AppLog.i(CONNECT, "Metadata successfully loaded");

                AppLog.i(CONNECT, "APP_ID = [" + appID + "]");
                AppLog.i(CONNECT, "CLIENT_PACKAGE = [" + clientPackage + "]");

                AppLog.i(CONNECT, "deviceID: [" + deviceID + "]");
                AppLog.i(CONNECT, "deviceName: [" + deviceName + "]");
                AppLog.i(CONNECT, "deviceType: [" + deviceType + "]");
                AppLog.i(CONNECT, "libraryVersion: [" + libraryVersion + "]");
                AppLog.i(CONNECT, "deviceOSVersion: [" + deviceOSVersion + "]");

                AppLog.i(CONNECT, "COUNTRY_CODE: [" + deviceCountryCode + "]");
                AppLog.i(CONNECT, "LANGUAGE_CODE: [" + deviceLanguage + "]");

                AppLog.i(CONNECT, "referralURL: [" + referralURL + "]");

                AppLog.i(CONNECT, "primaryColor: [" + primaryColor + "]");
                AppLog.i(CONNECT, "primaryColor: [" + Integer.toHexString(primaryColor) + "]");
            }
            else
            {
                AppLog.e(CONNECT, "Add APP_ID to AndroidManifest.xml file.");
            }

        }
        catch (NameNotFoundException e)
        {
            AppLog.e(CONNECT, "Add APP_ID to AndroidManifest.xml file.");
        }
    }


    /**
     * Helper类来执行在后台连接调用.
     */
    private class ConnectTask extends AsyncTask<Void, Void, Boolean>
    {
        @Override
        protected Boolean doInBackground(Void... params)
        {
            boolean returnValue = false;

            // http请求返回结果.
            String result = appURLConnection.connectToURL(SERVICE_URL + CONNECT_URL_PATH, urlParams);

            // 处理响应一个连接调用.
            if (result != null)
                returnValue = handleConnectResponse(result);

            return returnValue;
        }
    }


    /**
     * Helper类后台调用，获取积分.
     */
    private class ConnectGetPointsTask extends AsyncTask<Void, Void, Boolean>
    {
        @Override
        protected Boolean doInBackground(Void... params)
        {
            boolean returnValue = false;

            // http请求返回结果.
            String result = appURLConnection.connectToURL(SERVICE_URL + USERDATA_URL_PATH, urlParams);

            // 处理响应一个连接调用.
            if (result != null)
            {
                returnValue = handleGetPointsResponse(result);
            }

            // 失败处理
            if (returnValue == false)
                updatePointsNotifier.getUpdatePointsFailed("Failed to retrieve points from server");

            return returnValue;
        }
    }


    /**
     * Helper类后台调用，消费积分.
     */
    private class ConnectSpendPointsTask extends AsyncTask<Void, Void, Boolean>
    {
        @Override
        protected Boolean doInBackground(Void... params)
        {
            boolean returnValue = false;

            String url = SERVICE_URL + SPEND_POINTS_URL_PATH;
            String url_params = urlParams;
            url_params += "&" + SPEND_POINTS + "=" + spendPoints;
            String result = appURLConnection.connectToURL(url, url_params);

            if (result != null)
            {
                returnValue = handleSpendPointsResponse(result);
            }

            if (returnValue == false)
                updatePointsNotifier.getUpdatePointsFailed("Failed to spend points.");
//                spendPointsNotifier.getSpendPointsResponseFailed("Failed to spend points.");

            return returnValue;
        }
    }


    /**
     * 处理服务器请求的返回.
     * @param response		服务器端处理HTTP的返回
     * @return
     */
    private boolean handleConnectResponse(String response)
    {
        // 创建XML解析.
        Document document = buildDocument(response);

        if (document != null)
        {
            String nodeValue = getNodeTrimValue(document.getElementsByTagName("Success"));

            //成功.
            if (nodeValue != null && nodeValue.equals("true"))
            {
                AppLog.i(CONNECT, "Successfully connected to waps site.");
                return true;
            }
            else
            {
                AppLog.e(CONNECT, " Connect call failed.");
            }
        }

        return false;
    }


    /**
     * 处理获取几根的请求.
     * @param response
     * @return
     */
    private boolean handleGetPointsResponse(String response)
    {
        // 创建XML解析
        Document document = buildDocument(response);

        if (document != null)
        {
            String nodeValue = getNodeTrimValue(document.getElementsByTagName("Success"));

            // 成功
            if (nodeValue != null && nodeValue.equals("true"))
            {

                // 获取到积分数
                String pointsTotal = getNodeTrimValue(document.getElementsByTagName("Points"));
                String currencyName = getNodeTrimValue(document.getElementsByTagName("CurrencyName"));


                if (pointsTotal != null && currencyName != null)
                {

                    // 触发.
                    updatePointsNotifier.getUpdatePoints(currencyName, Integer.parseInt(pointsTotal));
                    return true;
                }
                else
                {
                    AppLog.e(CONNECT, "Invalid XML: Missing tags.");
                }
            }
            else
            {
                AppLog.e(CONNECT, "Invalid XML: Missing <Success> tag.");
            }
        }

        return false;
    }


    /**
     * 处理消费点数的返回结果.
     * @param response
     * @return
     */
    private boolean handleSpendPointsResponse(String response)
    {
        String message = "";

        // 创建XML解析.
        Document document = buildDocument(response);

        if (document != null)
        {
            String nodeValue = getNodeTrimValue(document.getElementsByTagName("Success"));

            // 成功处理
            if (nodeValue != null && nodeValue.equals("true"))
            {

                String pointsTotal = getNodeTrimValue(document.getElementsByTagName("Points"));
                String currencyName = getNodeTrimValue(document.getElementsByTagName("CurrencyName"));

                if (pointsTotal != null && currencyName != null)
                {

                    updatePointsNotifier.getUpdatePoints(currencyName, Integer.parseInt(pointsTotal));
//                    spendPointsNotifier.getSpendPointsResponse(currencyName, Integer.parseInt(pointsTotal));
                    return true;
                }
                else
                {
                    AppLog.e(CONNECT, "Invalid XML: Missing tags.");
                }
            }
            else
                // 错误处理.
                if (nodeValue != null && nodeValue.endsWith("false"))
                {
                    message = getNodeTrimValue(document.getElementsByTagName("Message"));
                    AppLog.i(CONNECT, message);

                    updatePointsNotifier.getUpdatePointsFailed(message);
//                    spendPointsNotifier.getSpendPointsResponseFailed(message);
                    return true;
                }
                else
                {
                    AppLog.e(CONNECT, "Invalid XML: Missing <Success> tag.");
                }
        }

        return false;
    }


    /**
     * 将String类型XML,构造成Document类型.
     * @param xml
     * @return
     */
    private Document buildDocument(String xml)
    {
        Document document = null;

        try
        {
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder documentBuilder;

            InputStream is = new ByteArrayInputStream(xml.getBytes("UTF-8"));

            documentBuilder = factory.newDocumentBuilder();
            document = documentBuilder.parse(is);
        }
        catch (Exception e)
        {
            AppLog.e(CONNECT, "buildDocument exception: " + e.toString());
        }

        return document;
    }


    /**
     * 解析返回的XML结果.
     * @param nodeList
     * @return
     */
    private String getNodeTrimValue(NodeList nodeList)
    {
        Element element = (Element) nodeList.item(0);
        String nodeValue = "";
        if (element != null)
        {
            NodeList itemNodeList = element.getChildNodes();

            int length = itemNodeList.getLength();
            for (int i = 0; i < length; i++)
            {
                Node node = ((Node) itemNodeList.item(i));
                if (node != null)
                    nodeValue += node.getNodeValue();
            }

            if (nodeValue != null && !nodeValue.equals(""))
            {
                return nodeValue.trim();
            }
            else
            {
                return null;
            }
        }
        return null;
    }


    /**
     * 释放连接对象. 必须在应用退出时调用.
     */
    public void finalize()
    {
        appConnectInstance = null;
        AppLog.i(CONNECT, "Cleaning resources.");
    }


    /**
     * Helper方法.
     */
    private void getPointsHelper()
    {
        connectGetPointsTask = new ConnectGetPointsTask();
        connectGetPointsTask.execute();
    }


    /**
     * Helper方法.
     */
    private void spendPointsHelper()
    {
        connectSpendPointsTask = new ConnectSpendPointsTask();
        connectSpendPointsTask.execute();
    }


    // OFFERS相关方法
    /**
     * 显示Offer (IMEI/MEID).
     * @param ctx 		The Activity Context.
     */
    public void showOffers(Context ctx)
    {
        AppLog.i(CONNECT, "Showing offers without userID.");
        showOffers(ctx, deviceID);
    }


    /**
     * 使用 publisher_ID 显示 offers .
     * @param ctx
     * @param userID
     */
    public void showOffers(Context ctx, String userID)
    {
        AppLog.i(CONNECT, "Showing offers (userID = " + userID + ")");

        Intent offersIntent = new Intent(ctx, OffersWebView.class);
        offersIntent.putExtra(EXTRA_USER_ID, userID);
        offersIntent.putExtra(EXTRA_URL_PARAMS, urlParams);
        offersIntent.putExtra(EXTRA_CLIENT_PACKAGE, clientPackage);
        ctx.startActivity(offersIntent);
    }

    /**
     * 取得虚拟货币信息
     * @param notifier
     */
    public void getPoints(UpdatePointsNotifier notifier)
    {
        if (appConnectInstance != null)
        {
            updatePointsNotifier = notifier;
            appConnectInstance.getPointsHelper();
        }
    }


    /**
     * 消费虚拟货币
     * @param notifier
     */
    public void spendPoints(int amount, UpdatePointsNotifier notifier)
    {
        if (amount < 0)
        {
            AppLog.e(CONNECT, "spendPoints error: 金额必须为正数");
            return;
        }

        spendPoints = "" + amount;

        if (appConnectInstance != null)
        {
            updatePointsNotifier = notifier;
//            spendPointsNotifier = notifier;
            appConnectInstance.spendPointsHelper();
        }
    }


    public void getDisplayAd(DisplayAdNotifier notifier)

    {
        String displayAdURLParams = urlParams;
        displayAd.getDisplayAdDataFromServer(SERVICE_URL, displayAdURLParams, notifier);
    }

}
